package com.settlement.system.controller;

import com.settlement.system.csv.CsvExportBuilder;
import com.settlement.system.csv.CsvExportUtil;
import com.settlement.system.csv.Header;
import com.settlement.system.csv.Headers;
import com.settlement.system.common.enums.CommonCode;
import com.settlement.system.common.enums.ExcelFileType;
import com.settlement.system.common.enums.QueryTypeEnum;
import com.settlement.system.common.enums.ReturnStatusEnum;
import com.settlement.system.common.exception.ServiceException;
import com.settlement.system.model.entity.common.TblQueryJoinTable;
import com.settlement.system.reply.ObjectDataResponse;
import com.settlement.system.service.IBaseService;
import com.settlement.system.service.ITblQueryJoinTableService;
import com.settlement.system.service.csv.TblQueryJoinTableCsvDatas;
import com.settlement.system.common.util.common.QueryJoinTableUtil;
import com.settlement.system.common.util.common.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 联表查询主表 前端控制器
 * @author xiaochuan
 * @since 2022-01-13
 */

@Slf4j
@Api(tags = "联表查询主表",description = "联表查询主表")
@RestController
@RequestMapping("/tblQueryJoinTable")
public class TblQueryJoinTableController extends ExcelController<TblQueryJoinTable> {

    @Value("${system.export-root.path}")
    private String exportRootPath;

    private static final Pattern COMPILE  = Pattern.compile("[\\u4e00-\\u9fa5]{1,}");


    @Resource
    private ITblQueryJoinTableService tblQueryJoinTableService;

    @Override
    public IBaseService init() {
        return tblQueryJoinTableService;
    }

    @Override
    public Class<?> getModelClass() {
        return TblQueryJoinTable.class;
    }

    /**
     * 插入，修改方法会调用此方法
     */
    @Override
    protected void setModelValue(TblQueryJoinTable model) throws Exception {

        //需要拼接条件sql
        tblQueryJoinTableService.appendCondition(model);
        tblQueryJoinTableService.appendGroupCondition(model);
    }

    @Override
    protected ObjectDataResponse insert(@RequestBody TblQueryJoinTable model, HttpServletRequest request) {
        try {
            setDefualt(model);
            setModelValue(model);
            //SQL格式校验规则
            tblQueryJoinTableService.sqlMatcher(model);
            tblQueryJoinTableService.groupSqlMatcher(model);
            if(!model.isSuccess()){
                model.setErrorMsg(StrUtil.append("新增失败，查询名称：", model.getQueryName(),"，"+model.getErrorMsg()+"，请检查。"));
                return new ObjectDataResponse(model,200, model.getErrorMsg());
            }

            Map<String, Object> params = new HashMap<String, Object>(16);
            params.put("queryName", model.getQueryName());
            if (tblQueryJoinTableService.selectCount(params) > CommonCode.ZERO.code()) {
                model.setErrorMsg("新增失败，查询名称：" + model.getQueryName() + "，存在条件重复数据。");
                return new ObjectDataResponse(model,200, model.getErrorMsg());
            }
            baseService.insert(model);
            model.setErrorMsg("新增成功");
            return new ObjectDataResponse(model,200, model.getErrorMsg());
        } catch (Exception ex) {
            log.info("新增数据异常", ex);
            return new ObjectDataResponse(500, "新增失败，请联系管理员！");
        }
    }

    @Override
    protected ObjectDataResponse update(@RequestBody TblQueryJoinTable model, HttpServletRequest request) {
        try {
            setDefualt(model);
            setModelValue(model);
            //SQL格式校验规则
            tblQueryJoinTableService.sqlMatcher(model);
            tblQueryJoinTableService.groupSqlMatcher(model);

            if(!model.isSuccess()){
                model.setErrorMsg(StrUtil.append("修改失败，查询名称：", model.getQueryName(),"，"+model.getErrorMsg()+"，请检查。"));
                return new ObjectDataResponse(model,200, model.getErrorMsg());
            }
            TblQueryJoinTable params=new TblQueryJoinTable();
            params.setQueryName(model.getQueryName());
            TblQueryJoinTable recordProjectMain = tblQueryJoinTableService.selectSingleByModel(params);
            if (recordProjectMain!=null && !recordProjectMain.getId().equals(model.getId())) {
                model.setErrorMsg("修改失败，查询名称：" + model.getQueryName() + "，存在条件重复数据。");
                return new ObjectDataResponse(model,200, model.getErrorMsg());
            }
            baseService.update(model);
            model.setErrorMsg("更新成功");
            return new ObjectDataResponse(model,200, model.getErrorMsg());
        } catch (Exception ex) {
            log.info("更新数据异常", ex);
            return new ObjectDataResponse(500, "更新失败，请联系管理员！"+ ex.getCause()!=null ? ex.getCause().getMessage() : "");
        }
    }

    @Override
    public void exportExcelPost(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> params) throws Exception {
        setParamsModel(params);
        String queryName = (String) params.get("queryName");
        String fileType = (String) params.get("fileType");
        String queryType = (String) params.get("queryType");
        if(StringUtils.isEmpty(queryName)){
            throw new ServiceException("查询名不能为空");
        }
        String returnStr = "";
        TblQueryJoinTable tblQueryJoinTable = new TblQueryJoinTable();
        tblQueryJoinTable.setQueryName(queryName);
        tblQueryJoinTable = tblQueryJoinTableService.selectSingleByModel(tblQueryJoinTable);
        if(tblQueryJoinTable != null){
            if(QueryTypeEnum.MX_QUERY.getNo().equals(queryType)){
                returnStr = QueryJoinTableUtil.decode(tblQueryJoinTable.getReturnStr());
            }
            if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(queryType)){
                if(StringUtils.isEmpty(tblQueryJoinTable.getGroupFields()) || StringUtils.isEmpty(tblQueryJoinTable.getSummaryFields())){
                    throw new ServiceException("未设置分组或汇总字段");
                }
                returnStr = QueryJoinTableUtil.decode(tblQueryJoinTable.getGroupSqlStr());
            }
        }
        tblQueryJoinTable.setQueryTypeNo(queryType);
        if(StringUtils.isNotBlank(returnStr)){
            returnStr = QueryJoinTableUtil.convertAccountingPeriodToOutDate(returnStr);
            params.put("ifMapData","true");
            params.put("sqlStr",returnStr);
            String path = exportRootPath + System.currentTimeMillis() + File.separator;

            if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(queryType)){
                queryName+= "_汇总";
            }else if(QueryTypeEnum.MX_QUERY.getNo().equals(queryType)){
                queryName+= "_明细";
            }

            CsvExportUtil.createCsv()
                    // 设置列宽，对XLSX有效
                    .columnWidthMap(getColumnWidthMap(tblQueryJoinTable))
                    .ifMapData(true)
                    .fileName(queryName)
                    .fileType(ExcelFileType.getByName(fileType))
                    // XLSX需要这个
                    .xlsxHeaderList(getMapDataXlsxHeaderList(tblQueryJoinTable))
                    // XLSX,CSV 都需要这个
                    .headers(getMapDataHeaderList(tblQueryJoinTable))
                    .model(CsvExportBuilder.MULTI_ZIP_MODEL)
                    .parentPath(path)
                    .csvDatas(new TblQueryJoinTableCsvDatas(tblQueryJoinTableService, params))
                    .export(request, response);
        }
    }

    /**
     * XLSX需要配置标题行
     * @param tblQueryJoinTable
     * @return
     */
    List<List<String>> getMapDataXlsxHeaderList(TblQueryJoinTable tblQueryJoinTable){
        String selectedFields = tblQueryJoinTable.getSelectedFields();
        if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(tblQueryJoinTable.getQueryTypeNo())){
            selectedFields = tblQueryJoinTable.getGroupFields()+","+tblQueryJoinTable.getSummaryFields();
        }
        String[] split = selectedFields.split(",");
        List<String> fieldsList = Arrays.asList(split);

        List<List<String>> headList = new ArrayList();
        List<String> headerList = new ArrayList();
        for (int index = 0; index < fieldsList.size(); index++) {
            headerList = new ArrayList();
            headerList.add(fieldsList.get(index).split("\\.")[1].trim());
            headList.add(headerList);
        }
        return headList;
    }

    /**
     * XLSX,CSV 都需要配置标题列表
     * @param tblQueryJoinTable
     * @return
     */
    private Headers getMapDataHeaderList(TblQueryJoinTable tblQueryJoinTable) {
        String selectedFields = tblQueryJoinTable.getSelectedFields();
        if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(tblQueryJoinTable.getQueryTypeNo())){
            selectedFields = tblQueryJoinTable.getGroupFields()+","+tblQueryJoinTable.getSummaryFields();
        }
        String[] split = selectedFields.split(",");
        List<String> fieldDescList = Arrays.asList(split);

        String sqlStr = QueryJoinTableUtil.decode(tblQueryJoinTable.getSqlStr());
        if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(tblQueryJoinTable.getQueryTypeNo())){
            sqlStr = QueryJoinTableUtil.decode(tblQueryJoinTable.getGroupSqlStr());
        }
        sqlStr = sqlStr.replace("SELECT ","");
        String selectedFieldNames = sqlStr.split(" FROM")[0];
        String[] split1 = selectedFieldNames.split(",");
        List<String> fieldNameList = Arrays.asList(split1);

        List<Header> currentList = new ArrayList<>();
        for (int i=0;i<fieldDescList.size();i++) {

            Header header = new Header();
            header.setTitle(fieldDescList.get(i).split("\\.")[1]);
            header.setField(fieldNameList.get(i).split("\\.")[1].trim());

            if(QueryTypeEnum.SUMMARY_QUERY.getNo().equals(tblQueryJoinTable.getQueryTypeNo())
                    && fieldNameList.get(i).contains(".")
                    && fieldNameList.get(i).contains(") ")
                    && fieldNameList.get(i).contains("SUM")){
                header.setField(fieldNameList.get(i).split("\\) ")[1].trim());
            }

            header.setOrder(i);
            currentList.add(header);
        }
        return new Headers(currentList);
    }

    /**
     * 针对XLSX 的列宽配置
     * @param tblQueryJoinTable
     * @return
     */
    Map<Integer, Integer> getColumnWidthMap (TblQueryJoinTable tblQueryJoinTable){
        String selectedFields = tblQueryJoinTable.getSelectedFields();
        String[] split = selectedFields.split(",");
        Map<Integer, Integer> map = new HashMap<>();
        for(int i=0;i< split.length;i++){
            map.put(i,calcColumnWidth(split[i].split("\\.")[1]));
        }
        return map;
    }

    /**
     * 计算列宽，字符串中汉字900宽度，非汉字400宽度。保证标题能完整显示。
     * @param str
     * @return
     */
    public int calcColumnWidth(String str){
        int width = 0;
        for(int i=0;i< str.length();i++){
            String substring = str.substring(i, i + 1);
            if(isChinese(substring)){
                width+=800;
            }else{
                width+=400;
            }
        }
        if(width < 800 * 6){
            width = 800 * 6;
        }
        if(width > 800 * 12){
            width = 800 * 12;
        }
        return width;
    }

    /**
     * 判断单个字符是否是汉字
     * @param str
     * @return
     */
    boolean isChinese(String str){
        Matcher matcher = COMPILE.matcher(str);
        boolean matches = matcher.matches();
        return matches;
    }

    @ApiOperation("批量复制")
    @RequestMapping(value = "batchCopy", method = {RequestMethod.POST})
    @ResponseBody
    protected ObjectDataResponse batchCopy(@RequestBody List<TblQueryJoinTable> copyList, HttpServletRequest request) {
        try {
            String message = tblQueryJoinTableService.checkBeforeCopy(copyList);
            if (StringUtils.isEmpty(message)) {
                return new ObjectDataResponse(ReturnStatusEnum.REQUEST_SUCCESS);
            } else {
                return new ObjectDataResponse(ReturnStatusEnum.REQUEST_ABNORMAL.getValue(), message);
            }
        } catch (Exception ex) {
            log.info("更新数据异常", ex);
            return new ObjectDataResponse(ReturnStatusEnum.REQUEST_ABNORMAL);
        }
    }
}

